# Released under the MIT License. See LICENSE for details.
#
"""Defines the nearby tab in the gather UI."""

from __future__ import annotations

import weakref
from typing import TYPE_CHECKING

import ba
import _ba
from bastd.ui.gather import GatherTab

if TYPE_CHECKING:
    from typing import Optional, Any
    from bastd.ui.gather import GatherWindow


class NetScanner:
    """Class for scanning for games on the lan."""

    def __init__(self, tab: GatherTab, scrollwidget: ba.Widget,
                 tab_button: ba.Widget, width: float):
        self._tab = weakref.ref(tab)
        self._scrollwidget = scrollwidget
        self._tab_button = tab_button
        self._columnwidget = ba.columnwidget(parent=self._scrollwidget,
                                             border=2,
                                             margin=0,
                                             left_border=10)
        ba.widget(edit=self._columnwidget, up_widget=tab_button)
        self._width = width
        self._last_selected_host: Optional[dict[str, Any]] = None

        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self.update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        # Go ahead and run a few *almost* immediately so we don't
        # have to wait a second.
        self.update()
        ba.timer(0.25, ba.WeakCall(self.update), timetype=ba.TimeType.REAL)

    def __del__(self) -> None:
        _ba.end_host_scanning()

    def _on_select(self, host: dict[str, Any]) -> None:
        self._last_selected_host = host

    def _on_activate(self, host: dict[str, Any]) -> None:
        _ba.connect_to_party(host['address'])

    def update(self) -> None:
        """(internal)"""

        # In case our UI was killed from under us.
        if not self._columnwidget:
            print(f'ERROR: NetScanner running without UI at time'
                  f' {ba.time(timetype=ba.TimeType.REAL)}.')
            return

        t_scale = 1.6
        for child in self._columnwidget.get_children():
            child.delete()

        # Grab this now this since adding widgets will change it.
        last_selected_host = self._last_selected_host
        hosts = _ba.host_scan_cycle()
        for i, host in enumerate(hosts):
            txt3 = ba.textwidget(parent=self._columnwidget,
                                 size=(self._width / t_scale, 30),
                                 selectable=True,
                                 color=(1, 1, 1),
                                 on_select_call=ba.Call(self._on_select, host),
                                 on_activate_call=ba.Call(
                                     self._on_activate, host),
                                 click_activate=True,
                                 text=host['display_string'],
                                 h_align='left',
                                 v_align='center',
                                 corner_scale=t_scale,
                                 maxwidth=(self._width / t_scale) * 0.93)
            if host == last_selected_host:
                ba.containerwidget(edit=self._columnwidget,
                                   selected_child=txt3,
                                   visible_child=txt3)
            if i == 0:
                ba.widget(edit=txt3, up_widget=self._tab_button)


class NearbyGatherTab(GatherTab):
    """The nearby tab in the gather UI"""

    def __init__(self, window: GatherWindow) -> None:
        super().__init__(window)
        self._net_scanner: Optional[NetScanner] = None
        self._container: Optional[ba.Widget] = None

    def on_activate(
        self,
        parent_widget: ba.Widget,
        tab_button: ba.Widget,
        region_width: float,
        region_height: float,
        region_left: float,
        region_bottom: float,
    ) -> ba.Widget:
        c_width = region_width
        c_height = region_height - 20
        sub_scroll_height = c_height - 85
        sub_scroll_width = 650
        self._container = ba.containerwidget(
            parent=parent_widget,
            position=(region_left,
                      region_bottom + (region_height - c_height) * 0.5),
            size=(c_width, c_height),
            background=False,
            selection_loops_to_parent=True)
        v = c_height - 30
        ba.textwidget(parent=self._container,
                      position=(c_width * 0.5, v - 3),
                      color=(0.6, 1.0, 0.6),
                      scale=1.3,
                      size=(0, 0),
                      maxwidth=c_width * 0.9,
                      h_align='center',
                      v_align='center',
                      text=ba.Lstr(resource='gatherWindow.'
                                   'localNetworkDescriptionText'))
        v -= 15
        v -= sub_scroll_height + 23
        scrollw = ba.scrollwidget(parent=self._container,
                                  position=((region_width - sub_scroll_width) *
                                            0.5, v),
                                  size=(sub_scroll_width, sub_scroll_height))

        self._net_scanner = NetScanner(self,
                                       scrollw,
                                       tab_button,
                                       width=sub_scroll_width)

        ba.widget(edit=scrollw, autoselect=True, up_widget=tab_button)
        return self._container

    def on_deactivate(self) -> None:
        self._net_scanner = None
